// 数据包后面添加标记符号，然后在前面添加长度
package wirepack

import (
	"bytes"
	"encoding/binary"
	"errors"
)

const LENPKT = "lenpkt"

var FLAGPAD = []byte("\r\n")

type LenPkt struct {
	buf []byte
}

func NewLenPkt() *LenPkt {
	return &LenPkt{
		buf: make([]byte, 0),
	}
}

func (p *LenPkt) Protocol() string {
	return LENPKT
}

func (p *LenPkt) Pack(buf []byte) []byte {
	buf = ByteSliceCombine(buf, FLAGPAD)
	b := make([]byte, 4)
	binary.BigEndian.PutUint32(b, uint32(len(buf)))
	return ByteSliceCombine(b, buf)
}

func (p *LenPkt) Cache(buf []byte) {
	p.buf = ByteSliceCombine(p.buf, buf)
}

func (p *LenPkt) Unpack() ([]byte, error) {
	// log.Println("LenPkt Unpack:", len(p.buf))

	if len(p.buf) < 4 {
		// 长度字节不够
		return nil, nil
	}

	// 获取长度
	l := int(binary.BigEndian.Uint32(p.buf)) // 数据长度，包含标志数据，不包括4个长度字节
	pl := len(FLAGPAD)                       // 标志数据长度

	if len(p.buf) < l+4 {
		// 数据不够
		if len(p.buf) > MaxPacketLen {
			p.buf = p.buf[MaxPacketLen:]
			return nil, errors.New("LenPkt Unpack exceed max len")
		}

		return nil, nil // 不能解包，数据可能不够
	}

	// 获取数据
	dat, flag := p.buf[4:l+4-pl], p.buf[l+4-pl:l+4]
	p.buf = p.buf[l+4:]

	if !bytes.Equal(flag, FLAGPAD) {
		return dat, errors.New("LenPkt Unpack invalid flag") //  标志无效
	}

	return dat, nil

}
